package encrypt

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"errors"
)

//高级加密标准 （Adevanced Encryption Standard ,Aes）

//16,24,32位字符串的话，分别对应AES-128,AES-192,AES-256加密方法
var PwdKey = []byte("DIS**#HKKOPJDEWQ")

//PKCS7 填充模式
func PKCS7Padding(ciphertext []byte,blockSize int)[]byte  {
	padding := blockSize-len(ciphertext) % blockSize
	//Repeat()函数的功能是把切片[]byte{byte(padding)复制padding个,然后合并成新的字节切片返回
	padtext := bytes.Repeat([]byte{byte(padding)},padding)
	return append(ciphertext,padtext...)
}
//填充的反向操作，删除填充的字符串
func PKCS7UnPadding(origData []byte)([]byte,error)  {
	//获取数据长度
	length := len(origData)
	if length == 0{
		return nil,errors.New("加密字符串错误")
	}else {
		//获取填充字符串长度
		unpadding := int(origData[length-1])
		//截取切片，删除填充字节，并返回明文
		return origData[:(length-unpadding)],nil
	}

}

//实现加密
func AesEcrypt(origData []byte,key []byte)([]byte,error)  {
	//创建加密的算法实例
	block,err := aes.NewCipher(key)
	if err != nil{
		return nil, err
	}
	//获取块的大小
	blockSize := block.BlockSize()
	//对数据进行填充，让数据长度满足需求
	origData = PKCS7Padding(origData,blockSize)
	//采用AES加密方法中CBC加密模式
	blocMode := cipher.NewCBCDecrypter(block,key[:blockSize])
	cryted := make([]byte,len(origData))
	//执行加密
	blocMode.CryptBlocks(cryted,origData)
	return cryted,nil
}
//加密base64
func EnPwdCode(pwd []byte)(string,error)  {
	result,err := AesEcrypt(pwd,PwdKey)
	if err != nil{
		return "", err
	}
	return base64.StdEncoding.EncodeToString(result),err
}

//实现解密
func AesDeCrypt(cryted []byte,key []byte)([]byte,error)  {
	//创建加密算法实例
	block,err := aes.NewCipher(key)
	if err != nil{
		return nil,err
	}
	//获取块大小
	blockSize := block.BlockSize()
	//创建加密客户端实例
	blockMode := cipher.NewCBCDecrypter(block,key[:blockSize])
	origiData := make([]byte,len(cryted))
	//这个函数也可以用来解密
	blockMode.CryptBlocks(origiData,cryted)
	//去除填充字符串
	origiData,err = PKCS7UnPadding(origiData)
	if err != nil{
		return nil,err
	}
	return origiData,err
}

//
func DePwsCode(pwd string)([]byte,error)  {
	//解密base64字符串
	pwdByte,err := base64.StdEncoding.DecodeString(pwd)
	if err != nil{
		return nil,err
	}
	//执行Aes解密
	return AesDeCrypt(pwdByte,PwdKey)
}

